<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<title>Mali OpenCL SDK v1.1.0: Mandelbrot</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="navtree.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="resize.js"></script>
<script type="text/javascript" src="navtree.js"></script>
<script type="text/javascript">
  $(document).ready(initResizable);
</script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/search.js"></script>
<script type="text/javascript">
  $(document).ready(function() { searchBox.OnSelectItem(0); });
</script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td id="projectlogo"><img alt="Logo" src="logo.png"/></td>
  <td style="padding-left: 0.5em;">
   <div id="projectname">Mali OpenCL SDK v1.1.0
   </div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.2 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "search",false,'Search');
</script>
  <div id="navrow1" class="tabs">
    <ul class="tablist">
      <li><a href="index.html"><span>Home</span></a></li>
      <li class="current"><a href="pages.html"><span>Help&#160;and&#160;Tutorials</span></a></li>
      <li><a href="files.html"><span>Files</span></a></li>
      <li>
        <div id="MSearchBox" class="MSearchBoxInactive">
        <span class="left">
          <img id="MSearchSelect" src="search/mag_sel.png"
               onmouseover="return searchBox.OnSearchSelectShow()"
               onmouseout="return searchBox.OnSearchSelectHide()"
               alt=""/>
          <input type="text" id="MSearchField" value="Search" accesskey="S"
               onfocus="searchBox.OnSearchFieldFocus(true)" 
               onblur="searchBox.OnSearchFieldFocus(false)" 
               onkeyup="searchBox.OnSearchFieldChange(event)"/>
          </span><span class="right">
            <a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.png" alt=""/></a>
          </span>
        </div>
      </li>
    </ul>
  </div>
</div><!-- top -->
<div id="side-nav" class="ui-resizable side-nav-resizable">
  <div id="nav-tree">
    <div id="nav-tree-contents">
      <div id="nav-sync" class="sync"></div>
    </div>
  </div>
  <div id="splitbar" style="-moz-user-select:none;" 
       class="ui-resizable-handle">
  </div>
</div>
<script type="text/javascript">
$(document).ready(function(){initNavTree('mandelbrot_tutorial.html','');});
</script>
<div id="doc-content">
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
<a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(0)"><span class="SelectionMark">&#160;</span>All</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(1)"><span class="SelectionMark">&#160;</span>Classes</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(2)"><span class="SelectionMark">&#160;</span>Files</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(3)"><span class="SelectionMark">&#160;</span>Functions</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(4)"><span class="SelectionMark">&#160;</span>Variables</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(5)"><span class="SelectionMark">&#160;</span>Macros</a><a class="SelectItem" href="javascript:void(0)" onclick="searchBox.OnSelectItem(6)"><span class="SelectionMark">&#160;</span>Pages</a></div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div class="header">
  <div class="headertitle">
<div class="title">Mandelbrot </div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p>The results of calculating the Mandelbrot set produces fractal patterns.</p>
<h1><a class="anchor" id="mandelbrotExampleResult"></a>
Example Result</h1>
<div class="image">
<img src="mandelbrot_output.bmp" alt="mandelbrot_output.bmp"/>
<div class="caption">
Output image</div></div>
 <h1><a class="anchor" id="mandelbrotAlgorithm"></a>
The Algorithm</h1>
<p>A complex number is in the Mandelbrot set if the it doesn't tend to infinity when a given equation is iterated on the number.</p>
<p>The equation used is:</p>
<p>z<sub>n+1</sub> = z<sub>n</sub><sup>2</sup> + c</p>
<p>where c is the complex number and n is the iteration. z<sub>0</sub> is set as 0.</p>
<p>To produce a visualization of the set, like the one shown above, you can treat the x and y pixel coordinates of an image as the real and imaginary components of a complex number. For example, at (2, 1) the complex number c = 2 + 1i.</p>
<p>It can be shown that if the distance from z<sub>n</sub> to the origin is greater than 2 for any value of <em>n</em>, it is unbounded and therefore not part of the Mandelbrot set.</p>
<p>Examples:</p>
<ul>
<li><p class="startli">Not in the Mandelbrot set:<br/>
 c = 2 + 1i<br/>
</p>
<p class="startli">z<sub>0</sub> = 0<br/>
 z<sub>1</sub> = 2 + 1i<br/>
</p>
<p class="startli">If you use 2 + 1i as coordinates (2, 1) then the euquidean distance to the origin is sqrt(2<sup>2</sup> + 1<sup>2</sup>) = 2.24.<br/>
 2.24 &gt; 2 and therefore for this input the equation is unbounded and the input is not part of the Mandelbrot set.</p>
</li>
<li><p class="startli">In the Mandelbrot set:<br/>
 c = 0 + 1i<br/>
</p>
<p class="startli">z<sub>0</sub> = 0<br/>
 z<sub>1</sub> = 0 + 1i<br/>
 z<sub>2</sub> = -1 + 1i<br/>
 z<sub>3</sub> = 0 - 1i<br/>
 z<sub>4</sub> = -1 + 1i<br/>
</p>
<p class="startli">You can see that this is forming a repeating pattern that will never become unbounded.</p>
</li>
</ul>
<p>To create the output image, the number of iterations taken to determine whether the point is or is not part of the Mandelbrot set is used as the pixel intensity. A limit is placed on the number of iterations such that cases like c = 0 + 1i do not run forever. Therefore, a pixel which is in the Mandelbrot set will have a value equal to the maximum number of iterations.</p>
<p>For more details see <a href="http://en.wikipedia.org/wiki/Mandelbrot_set">Wikipedia</a>.</p>
<h1><a class="anchor" id="mandelbrotImplementation"></a>
Implementation</h1>
<p>Unless otherwise noted, all code snippets come from the OpenCL kernel found in <a class="el" href="mandelbrot_8cl.html">mandelbrot.cl</a>.</p>
<ol type="1">
<li><p class="startli"><b>Choosing the size of the kernel</b></p>
<p class="startli">We are using vector types in the kernel and so we are actually outputting 4 results per kernel. See below for more details of vectorising. We split the data for the real and imaginary parts in order to be able to represent it.</p>
<p class="startli">We adjust the pointers into the data to reflect this: </p>
<div class="fragment"><div class="line">    <span class="comment">/*</span></div>
<div class="line"><span class="comment">     * Each kernel calculates 4 output pixels in the same row (hence the &#39;* 4&#39;).</span></div>
<div class="line"><span class="comment">     * x is in the range [0, width] in steps of 4.</span></div>
<div class="line"><span class="comment">     * y is in the range [0, height].</span></div>
<div class="line"><span class="comment">     */</span></div>
<div class="line">    <span class="keywordtype">int</span> x = get_global_id(0) * 4;</div>
<div class="line">    <span class="keywordtype">int</span> y = get_global_id(1);</div>
</div><!-- fragment --><p> And when we enqueue the kernel in <a class="el" href="mandelbrot_8cpp.html">mandelbrot.cpp</a>, we reduce the worksize accordingly: </p>
<div class="fragment"><div class="line">    <span class="comment">/*</span></div>
<div class="line"><span class="comment">     * The OpenCL kernel calculates four pixels at a time (all in the same row).</span></div>
<div class="line"><span class="comment">     * Therefore, we only need to run the kernel width / 4 times in the x dimension.</span></div>
<div class="line"><span class="comment">     */</span></div>
<div class="line">    <span class="keywordtype">size_t</span> globalWorksize[2] = {width / 4, height};</div>
</div><!-- fragment --></li>
<li><p class="startli"><b>Creating the inputs</b></p>
<p class="startli">Mali-T600 series GPU pipelines provide true IEEE-754 single-precision floating-point math in hardware. Each Mali-T600 series GPU core has a minimum of two 128-bit wide ALUs (Arithmetic logic units). Each ALU can do a maximum of two vector floating point operations per cycle (one vector floating point addition and one vector floating point multiplication).</p>
<p class="startli">In this sample, the calculations use 32-bit floating point numbers. One 128-bit vector can fit four 32-bit floating point numbers. Therefore, using float4's makes maximum use of the hardware.</p>
<p class="startli">We recommend the use of vectors wherever possible when using a Mali-T600 series GPU.</p>
<p class="startli">Here we create the input vectors: </p>
<div class="fragment"><div class="line">    <span class="comment">/*</span></div>
<div class="line"><span class="comment">     * Calculate the coordinates of the four pixels in the real and imaginary space.</span></div>
<div class="line"><span class="comment">     * Scale the coordinates by the height and width such that the same image is produced for all values, just at different resolutions.</span></div>
<div class="line"><span class="comment">     * The real coordinate is scaled to the range [0, 2.5] (using &#39;/ width * 2.5f&#39;) and then shifted to be in the range [-2, 0.5] (using &#39;-2&#39;).</span></div>
<div class="line"><span class="comment">     * The imaginary coordinate is scaled to the range [0, 2] (using &#39;/ ((float) height) * 2&#39; and then shifted to be in the range [-1, 1] (using &#39;-1&#39;).</span></div>
<div class="line"><span class="comment">     * The resulting ranges ([-2, 0.5], [-1, 1]) are the limits of the interesting parts of the Mandelbrot set.</span></div>
<div class="line"><span class="comment">     * Four pixels (adjacent in x (real) dimension) are calulated per kernel instance. Therefore, we calculate real coordinates for 4 pixels.</span></div>
<div class="line"><span class="comment">     */</span></div>
<div class="line">    float4 initialReal = -2 + (<a class="code" href="mandelbrot_8cl.html#a4dffa8ed5ea4612c75f705e514351c4a" title="Create a float4 containing the x positions of x and the 3 adjacent pixels.">createStartX</a>(x) / (float)width * 2.5f);</div>
<div class="line">    float4 initialImaginary = -1 + (y / (float)height * 2);</div>
<div class="line"></div>
<div class="line">    float4 real = initialReal;</div>
<div class="line">    float4 imaginary = initialImaginary;</div>
</div><!-- fragment --></li>
<li><p class="startli"><b>Doing the calculation</b></p>
<p class="startli">All of the main calculations are done on vectors of 4 floating point numbers. Each vector calculation can be done as a single operation on Mali-T600 series GPU.</p>
<p class="startli">The main calculation loop: </p>
<div class="fragment"><div class="line">    <span class="comment">/*</span></div>
<div class="line"><span class="comment">     * Loop until we can say that all pixels are not part</span></div>
<div class="line"><span class="comment">     * of the Mandelbrot set or the maximum number of</span></div>
<div class="line"><span class="comment">     * iterations has been reached.</span></div>
<div class="line"><span class="comment">     */</span></div>
<div class="line">    <span class="keywordflow">do</span></div>
<div class="line">    {</div>
<div class="line">        iterations++;</div>
<div class="line">        <span class="keywordflow">if</span> (iterations &gt; <a class="code" href="mandelbrot_8cl.html#acd517c6f195c75b9dd0f3aad65326f3b">MAX_ITER</a>)</div>
<div class="line">        {</div>
<div class="line">            <span class="keywordflow">break</span>;</div>
<div class="line">        }</div>
<div class="line"></div>
<div class="line">        <span class="comment">/* Backup the real value as its used in both calculations but changed by the first. */</span></div>
<div class="line">        float4 oldReal = real;</div>
<div class="line"></div>
<div class="line">        <span class="comment">/* Evaluate the equation. */</span></div>
<div class="line">        real = real * real - imaginary * imaginary + initialReal;</div>
<div class="line">        imaginary = 2 * oldReal * imaginary + initialImaginary;</div>
<div class="line"></div>
<div class="line">        <span class="comment">/*</span></div>
<div class="line"><span class="comment">         * Calculate which indices to update.</span></div>
<div class="line"><span class="comment">         * Mathematically, if the result of the calculation becomes greater that 2, it will continue to infinity.</span></div>
<div class="line"><span class="comment">         * Therefore, if the result becomes greater than 2 it cannot be part of the Mandelbrot set and we stop adding to it&#39;s iteration count.</span></div>
<div class="line"><span class="comment">         * To get the absolute value of the calculation we have squared and added the components, therefore we must test it against</span></div>
<div class="line"><span class="comment">         * 4 (2 squared).</span></div>
<div class="line"><span class="comment">         */</span></div>
<div class="line">        float4 absoluteValue = real * real + imaginary * imaginary;</div>
<div class="line">        <span class="comment">/* For vector input isless(x, y) returns -1 per component if x &lt; y. */</span></div>
<div class="line">        mask = isless(absoluteValue, (float4) 4.0f);</div>
<div class="line">        <span class="comment">/* Increase the iterations per pixel (if they are less than 4). */</span></div>
<div class="line">        iterationsPerPixel -= mask;</div>
<div class="line">    } <span class="keywordflow">while</span>(any(mask));</div>
</div><!-- fragment --></li>
<li><p class="startli"><b>Storing the results</b></p>
<p class="startli">Finally we convert the data to unsigned chars and store the data.</p>
<p class="startli">Pixels in the Mandelbrot set will have the value of MAX_ITER.</p>
<p class="startli">We use a vector store to write out all 4 results at once: </p>
<div class="fragment"><div class="line">    <span class="comment">/*</span></div>
<div class="line"><span class="comment">     * Write the result to the output buffer.</span></div>
<div class="line"><span class="comment">     * Convert the output to unsigned char to make it easier to write to a bitmap.</span></div>
<div class="line"><span class="comment">     */</span></div>
<div class="line">    vstore4(convert_uchar4(iterationsPerPixel), 0, output + x + y * width);</div>
</div><!-- fragment --> </li>
</ol>
<h1><a class="anchor" id="mandelbrotRunning"></a>
Running the Sample</h1>
<p>From a command prompt in the root of the SDK, run:</p>
<ol type="1">
<li><p class="startli">From a command prompt in the root of the SDK, run:</p>
<div class="fragment"><div class="line">cd samples/<a class="code" href="mandelbrot_8cl.html#aa9c49529b3f34c7675aedea1b068ef9a" title="Mandelbrot kernel function.">mandelbrot</a></div>
</div><!-- fragment --> <div class="fragment"><div class="line">make install</div>
</div><!-- fragment --><p class="startli">This compiles the Mandelbrot sample code and copies all the files it needs to run to the bin folder in the root directory of the SDK.</p>
</li>
<li>Copy this folder to the board.</li>
<li><p class="startli">Navigate to the folder on the board and run the Mandelbrot binary:</p>
<div class="fragment"><div class="line">./<a class="code" href="mandelbrot_8cl.html#aa9c49529b3f34c7675aedea1b068ef9a" title="Mandelbrot kernel function.">mandelbrot</a></div>
</div><!-- fragment --></li>
<li><p class="startli">You should see output similar to:</p>
<div class="fragment"><div class="line">Profiling information:</div>
<div class="line">Queued time:    0.087ms</div>
<div class="line">Wait time:      0.059914ms</div>
<div class="line">Run time:       14.3642ms</div>
</div><!-- fragment --><p class="startli">An output image should be created on the board called output.bmp.</p>
</li>
</ol>
<p>Find solutions for <a class="el" href="common_issues.html">Common Issues</a>.</p>
<h1><a class="anchor" id="mandelbrotMoreInformation"></a>
More Information</h1>
<p>For more information have a look at the code in <a class="el" href="mandelbrot_8cpp.html">mandelbrot.cpp</a> and <a class="el" href="mandelbrot_8cl.html">mandelbrot.cl</a>. </p>
</div></div><!-- contents -->
</div><!-- doc-content -->
<!-- start footer part -->
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
  <ul>
    <li class="navelem"><a class="el" href="tutorials.html">Tutorials</a></li>
    <li class="footer">
        <a href="http://www.arm.com/">(C) ARM Ltd. 2013</a>
    </li>
  </ul>
</div>
</body>
</html>
